package com.sgcc.pda.web.service;

import android.content.Context;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.sgcc.pda.baselibrary.utils.LogUtil;
import com.sgcc.pda.sdk.utils.DataConversionUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.concurrent.ThreadPoolExecutor;

import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import web.pda.sgcc.com.websdk.http.OkHttpManager;
import web.pda.sgcc.com.websdk.http.file.download.ThreadPool;

/**
 * 断点续传(下载大文件时使用)
 *
 * @author Ben
 * @date 2020/04/17 017
 */
public class FileWget {
    public static final int STATUS_START = -1;
    public static final int STATUS_STOP = -2;
    public static final int STATUS_FAIL = -3;
    public static final int STATUS_FINISH = 101;


    private OkHttpClient okHttpClient;
    private String serverUrl;// 文件下载服务路径
    private String fileUrl;// 文件地址Url
    private String savePath;// 文件保存路径
    private File saveFile;// 下载的文件
    private RandomAccessFile randomAccessFile; // 文件随机访问流

    private long completedSize = 0L;// 已下载大小
    private long fileSize = 0L;// 文件大小
    private boolean isDownloading = false; //是否下载中

    private final ThreadPoolExecutor executor;// 线程池
    private DownloadThread downloadThread;//线程
    private IDownloadProgress iDownloadProgress;// 下载进度方法，内部定义的抽象方法

    /**
     * 断点续传下载参数封装
     *
     * @param context   上下文对象
     * @param serverUrl 请求服务URL
     * @param fileUrl   下载文件URL
     * @param savePath  本地保存路径
     */
    public FileWget(@NonNull Context context, @NonNull String serverUrl, @NonNull String fileUrl, @NonNull String savePath) {
        this.okHttpClient = OkHttpManager.getClient(context);
        this.serverUrl = serverUrl;
        this.fileUrl = fileUrl;
        this.savePath = savePath;
        this.executor = ThreadPool.getInstance().getThreadPoolExecutor();
        // executor = new ThreadPoolExecutor(5, 5, 50, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3000));
    }


    /**
     * 开启线程，下载文件
     *
     * @param iDownloadProgress 下载进度回调
     */
    public void start(@Nullable IDownloadProgress iDownloadProgress) {
        this.iDownloadProgress = iDownloadProgress;
        if (downloadThread == null) {
            downloadThread = new DownloadThread();
            isDownloading = true;
            executor.execute(downloadThread);
            updateProgress(STATUS_START, "开始下载");
        }
    }

    /**
     * 停止线程，暂停下载
     */
    public void stop() {
        if (downloadThread != null) {
            isDownloading = false;
            executor.remove(downloadThread);
            downloadThread = null;
            updateProgress(STATUS_STOP, "停止下载");
        }
    }

    /**
     * 下载文件
     */
    private void downloadFile() {
        // 创建文件(读取文件已下载大小)
        completedSize = getCompletedSize();
        // 创建随机访问流
        createRandomAccessFile();
        // 获取文件总大小
        fileSize = getContentLength();
        if (fileSize < 0){
            updateProgress(STATUS_FAIL, "文件不存在");
            deleteFile();

            LogUtil.e("文件不存在");
            return;
        }

        if (completedSize > fileSize) {
            updateProgress(STATUS_FAIL, "文件长度获取出错，本地文件长度：" + completedSize + ", 服务端文件长度：" + fileSize);
            deleteFile();

            LogUtil.e("文件长度获取出错");
            return;
        }

        if (randomAccessFile == null) {
            updateProgress(STATUS_FAIL, "下载文件访问出错");
            deleteFile();

            LogUtil.e("下载文件访问出错");
            return;
        }
        if (completedSize == fileSize) {
            updateProgress(STATUS_FINISH, savePath);
            return;
        }

        Request request = new Request.Builder().url(genDownloadUrl()).build();
        try {
            // OkHttpClient client = new OkHttpClient();
            Response response = okHttpClient.newCall(request).execute();
            ResponseBody body = response.body();
            if (response.isSuccessful()) {
                if (body != null) {
                    InputStream inputStream = body.byteStream();
                    byte[] bytes = new byte[1024];
                    int len;
                    long timetemp = 0L;
                    while (isDownloading && (len = inputStream.read(bytes)) != -1) {
                        randomAccessFile.write(bytes, 0, len);
                        completedSize += len;
                        if (SystemClock.uptimeMillis() - timetemp > 1000L) {
                            timetemp = SystemClock.uptimeMillis();
                            updatePercent();
                        }
                    }
                }
                response.close();
                updateProgress(STATUS_FINISH, saveFile.getPath());
            } else {
                updateProgress(STATUS_FAIL, body != null ? body.string() : response.message());
                deleteFile();

                LogUtil.e(body != null ? body.string() : response.message());
            }
        } catch (IOException e) {
            e.getMessage();
            updateProgress(STATUS_FAIL, Log.getStackTraceString(e));

            LogUtil.e(Log.getStackTraceString(e));
        }
    }


    /**
     * 获取已下载文件的大小
     *
     * @return file size
     */
    private long getCompletedSize() {
        if (saveFile == null) {
            // 创建文件
            saveFile = new File(savePath);
        }
        // 文件已下载大小
        completedSize = saveFile.length();
        return completedSize;
    }

    /**
     * 创建随机文件访问流，在确保文件已经创建的后边
     */
    private void createRandomAccessFile() {
        if (randomAccessFile == null) {
            try {// 创建随机访问流
                randomAccessFile = new RandomAccessFile(saveFile, "rwd");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                updateProgress(STATUS_FAIL, Log.getStackTraceString(e));
            }
        }
        if (randomAccessFile != null) {
            try {// 更新随机流进度
                randomAccessFile.seek(completedSize);
            } catch (IOException e) {
                e.printStackTrace();
                updateProgress(STATUS_FAIL, Log.getStackTraceString(e));
            }
        }
    }

    /**
     * 通过OkHttpClient获取文件的大小
     *
     * @return 文件总大小
     */
    private long getContentLength() {
        long length = 0L;
        try {
            // OkHttpClient client = OkHttpManager.getClient(mContext);
            Request request = new Request.Builder().url(genGetLengthUrl()).build();
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                ResponseBody body = response.body();
                if (body != null) {
                    length = body.contentLength();
                }
                if (length <= 0) {
                    Headers headers = response.headers();
                    if (headers != null) {
                        String size = headers.get("fileSize");
                        if (size != null) {
                            try {
                                length = Long.parseLong(size);
                            } catch (NumberFormatException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            } else {
                // 响应码不是200,表示未找到文件
                length = -1;
            }
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return length;
    }

    /**
     * 获取文件长度URL
     *
     * @return URL
     */
    private String genGetLengthUrl() {
        String requestParams = "downPicFile?FILEPATH=" + fileUrl;
        return serverUrl + "&REQUEST_PARM=" + DataConversionUtil.str2HexStr(requestParams);
    }

    /**
     * 获取下载URL
     * 这个URL本来不想放在这儿的，但是接口要求的rangeKey参数是在requestParams中，没办法，接口名和参数就放在这里拼接
     *
     * @return URL
     */
    private String genDownloadUrl() {
        String requestParams = "downPicFile?FILEPATH=" + fileUrl
                + "&rangeKey=bytes:" + completedSize + "-" + fileSize;
        return serverUrl + "&REQUEST_PARM=" + DataConversionUtil.str2HexStr(requestParams);
    }


    /**
     * 更新下载百分比
     */
    private void updatePercent() {
        if (fileSize > 0) {
            final int percent = Math.round(completedSize * 100F / fileSize);
            updateProgress(percent, "当前的下载进度：" + percent + "%");
        }
    }

    /**
     * 更新回调接口
     *
     * @param percent 状态码(0~100表示下载进度)
     * @param message 消息内容
     */
    private void updateProgress(int percent, String message) {
        if (iDownloadProgress != null) {
            iDownloadProgress.downloadProgress(percent, message);
        }
    }

    /**
     * 下载失败时删除空文件
     */
    private void deleteFile(){
        if (saveFile != null){
            saveFile.delete();
        }
    }

    /**
     * 自定义线程
     */
    private class DownloadThread implements Runnable {
        @Override
        public void run() {
            downloadFile();
        }
    }

    /**
     * 文件下载进度接口
     */
    public interface IDownloadProgress {
        /**
         * 下载进度
         *
         * @param percent ( 0~100 表示下载进度, 其它值表示状态码)
         * @param message 消息内容
         */
        void downloadProgress(int percent, String message);
    }

}